package com.mingqijia.gassafety.webserver.webSocket;

import com.alibaba.fastjson.JSONObject;
import com.gap.cache.redis.RedisCache;
import com.mingqijia.gassafety.db.entity.Organization;
import com.mingqijia.gassafety.db.entity.vo.SelectRegionSpIdInfoVo;
import com.mingqijia.gassafety.shared.constant.Constants;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zhangfei
 * @version 1.0.0
 * @ClassName WebSocketProcess.java
 * @Description webSocket 消息，持不同客户端消息区分
 * @createTime 2022年06月13日
 */
@Slf4j
@Controller
@ServerEndpoint(value = "/webSocket/notify/dp/{spId}/{t}")
public class WebSocketDpProcess {


    private static final String sepa=";";

    private static ConcurrentHashMap<String, ConcurrentHashMap<String, WebSocketDpProcess>> concurrentHashMap
            = new ConcurrentHashMap<>(12);

    private RedisTopicSendTemplate redisTopicSendTemplate = SpringUtil.getBean(RedisTopicSendTemplate.class);
    
    /**
     * 会话对象
     **/
    private Session session;
    
    @Autowired
    RedisCache redisCache;


    @OnOpen
    public void onOpen(Session session,@PathParam("spId")String spId,
                       @PathParam("t")String t) {
        //每新建立一个连接，spId为key,this为value存储到map中
        this.session = session;
        ConcurrentHashMap<String, WebSocketDpProcess> hashMap = new ConcurrentHashMap<>();
        if (concurrentHashMap.get(spId)!=null&&concurrentHashMap.get(spId).keySet().size()>0){
            hashMap = concurrentHashMap.get(spId);
        }
        hashMap.put(spId+sepa+t, this);
        concurrentHashMap.put(spId, hashMap);
        log.info("WebSocketDpProcess: Open a websocket. id={}", spId);
    }


    @OnClose
    public void onClose(Session session,@PathParam("spId")String spId
    , @PathParam("t")String t) {
        //客户端连接关闭时，移除map中存储的键值对
        String key =spId +sepa+t;
        ConcurrentHashMap<String, WebSocketDpProcess> con = concurrentHashMap.get(spId);
        if (con!=null&&con.keySet().size()>0) {
            con.remove(key);
        }
        log.info("WebSocketDpProcess: close a websocket, 当前关闭回话客户端spId= {}", spId);
    }

    /**
     * 接收到客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message,@PathParam("spId") String spId) {
        log.info("WebSocketDpProcess-onMessage：WebSocketProcess={}"
                ,JSONObject.toJSONString(concurrentHashMap));
        log.info("WebSocketDpProcess: 接收消息来自客户端client spId={},msg={}", spId, message);
    }

    /**
     * 连接发生异常时候触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocketDpProcess：Error websocket:{} ", error);
    }

    /**
     * 根据spid区分客户端消息
     *
     * @param spId
     * @param message
     */
    public static void sendMessage(String spId, String message, List<String> spIds){
        log.info("本地大屏消息通知：spId={},message={},organizations={}",spId,message,spIds);
        //根据spId,从map中获取存储的webSocket对象
        log.info("WebSocketDpProcess-sendMessage：WebSocketProcess={}"
                ,JSONObject.toJSONString(concurrentHashMap));
        
        ConcurrentHashMap<String, WebSocketDpProcess> concurrentMapAlls=new ConcurrentHashMap<>();
        
        if (!CollectionUtils.isEmpty(spIds)){
            for (int i = 0; i < spIds.size(); i++) {
                String currSpId = spIds.get(i);
                ConcurrentHashMap<String, WebSocketDpProcess> concurrentMap = concurrentHashMap.get(currSpId);
                log.info("WebSocketDpProcess-concurrentMap:{}",JSONObject.toJSONString(concurrentMap));
                if (concurrentMap!=null)concurrentMapAlls.putAll(concurrentMap);
                log.info("WebSocketDpProcess-concurrentMapParents:{}",JSONObject.toJSONString(concurrentMapAlls));
            }
        }else{
            ConcurrentHashMap<String, WebSocketDpProcess> concurrentMap = concurrentHashMap.get(spId);
            log.info("WebSocketDpProcess-concurrentMap1:{}",JSONObject.toJSONString(concurrentMap));
            if (concurrentMap!=null)concurrentMapAlls.putAll(concurrentMap);
        }

        ConcurrentHashMap<String, WebSocketDpProcess> concurrentMap = concurrentHashMap.get("0");
        if (concurrentMap==null)concurrentMap=new ConcurrentHashMap<>();
        if (concurrentMapAlls!=null)concurrentMap.putAll(concurrentMapAlls);
        
        if (concurrentMap.isEmpty()){
            log.error("WebSocketDpProcess-sendMessage：concurrentHashMap={}"
                    ,JSONObject.toJSONString(concurrentHashMap));
            return;
        }
        log.info("WebSocketDpProcess-sendMessage：WebSocketProcess-concurrentMap={}"
                ,JSONObject.toJSONString(concurrentHashMap));
        concurrentMap.forEach((s, webSocketDpProcess) -> {
            if (!ObjectUtils.isEmpty(webSocketDpProcess)) {
                //当客户端是Open状态时，才能发送消息
                if (webSocketDpProcess.session.isOpen()) {
                    try {
                        webSocketDpProcess.session.getBasicRemote().sendText(message);
                    } catch (IOException e) {
                        log.error("WebSocketDpProcess-sendMessage-error:{}",e);
                    }
                } else {
                    log.error("WebSocketDpProcess：websocket session={} is closed(会话关闭) ", spId);
                }
            }
        });
    }
    


    //大屏消息推送
    public void redisTopicSendMsg(String spId, String message) {
        log.info("redisTopicSendMsg：spId={},message={}",spId,message);
        redisTopicSendTemplate.sendMsg(Constants.TOPIC_DP_WEBSOCKET,message+";;"+spId);
    }
}